// 1. 类型参数 (Type Parameters)
// 最常见的模板参数形式，使用 typename 或 class 关键字声明。
template <typename T> // 或 template<class T>
class Vector
{ /* ... */
};

// 2. 非类型参数 (Non-Type Parameters)
// 可以是整型常量、枚举常量、指针、引用等。
// 指模板参数本身是一个具体的值或常量，而不是一个类型
// 在实例化模板时必须提供具体的值。对于指针和引用类型的非类型参数，需要提供具有静态存储期(static storage duration)的对象的地址或引用。
// 非类型参数是在编译时就确定的常量值，可以是：
//      整数常量（如int, long, char等）
//      枚举常量
//      指向对象/函数/成员的指针
//      对象或函数的左值引用
//      std::nullptr_t（从C++11开始）
//      浮点类型和类类型（从C++20开始）

// 整型常量参数
// 这里的N是一个非类型参数，它是一个int值
template <int N>
class Array
{
private:
    int data[N]; // 使用N作为数组大小
public:
    int size() const { return N; }
};

// 使用时必须提供一个具体的整数值
Array<5> arr; // 创建一个大小为5的数组

// 指针参数
template <int *ptr>
class PointerWrapper
{ /* ... */
};

// 引用参数
template <const int &ref>
class ReferenceWrapper
{ /* ... */
};

// 3. 模板模板参数 (Template Template Parameters)
// 参数本身是一个模板。
// Container 是一个模板模板参数
template <template <typename> class Container>
class Wrapper
{
    Container<int> container;
};

// 4. 可变参数模板 (Variadic Templates)
// 接受任意数量的模板参数，使用 ... 语法。
// 您已经熟悉的形式
template <typename... Args>
void func(Args... args) { /* ... */ }

// 5. 默认模板参数 (Default Template Arguments)
// 为模板参数提供默认值。
// 默认类型为int，默认大小为10
template <typename T = int, size_t Size = 10>
class Array
{
private:
    T data[Size];

public:
    size_t size() const { return Size; }
    T &operator[](size_t index) { return data[index]; }
};

// 使用方式
int main()
{
    Array<> a1;           // T=int, Size=10
    Array<double> a2;     // T=double, Size=10
    Array<int, 5> a3;     // T=int, Size=5
    Array<double, 20> a4; // T=double, Size=20

    return 0;
}